"""
LMS主系统实现
此模块包含集成所有组件的主系统类
"""

from typing import Dict, Any, Optional
from datetime import datetime
import sys

# 导入管理器(这些将由其他团队成员实现)
from managers.user_manager import UserManager
from managers.course_manager import CourseManager
from managers.enrollment_manager import EnrollmentManager
from managers.assignment_manager import AssignmentManager

# 导入系统组件
from .auth_system import AuthenticationSystem
from .data_persistence import DataPersistence
from .analytics import Analytics
from .progress_tracker import ProgressTracker

# 导入模型类
from models.user import User, Student, Teacher, Admin
from models.course import Course

# 导入工具类
from utils.exceptions import LMSException


class LMSSystem:
    """
    LMS主系统类
    此类集成所有系统组件并提供主接口
    """

    _instance = None

    def __new__(cls):
        """
        单例模式实现
        """
        if cls._instance is None:
            cls._instance = super(LMSSystem, cls).__new__(cls)
        return cls._instance

    def __init__(self):
        """
        Initialize LMS system
        """
        # Check if already initialized to avoid re-initialization in singleton
        if hasattr(self, 'is_initialized'):
            return

        self.user_manager: Optional[UserManager] = None
        self.course_manager: Optional[CourseManager] = None
        self.enrollment_manager: Optional[EnrollmentManager] = None
        self.assignment_manager: Optional[AssignmentManager] = None
        self.auth_system: Optional[AuthenticationSystem] = None
        self.data_persistence: Optional[DataPersistence] = None
        self.progress_tracker: Optional[ProgressTracker] = None

        self.is_initialized = False
        self.start_time: Optional[datetime] = None

    def initialize(self) -> bool:
        """
        Initialize all system components

        Returns:
            bool: Returns True if initialization successful, False otherwise
        """
        try:
            # 初始化管理器(这些将由其他团队成员实现)
            self.user_manager = UserManager.get_instance()
            self.course_manager = CourseManager.get_instance()
            self.enrollment_manager = EnrollmentManager.get_instance()
            self.assignment_manager = AssignmentManager()

            # 初始化分析组件
            self.analytics = Analytics(self)
            # 初始化进度跟踪器（轻量级兼容层）
            self.progress_tracker = ProgressTracker(self)

            # 初始化系统组件
            self.auth_system = AuthenticationSystem()
            self.auth_system.set_user_manager(self.user_manager)
            self.data_persistence = DataPersistence()

            # Load data if persistence is available
            self.load_data()

            # Check if admin user exists, if not create default admin
            self._ensure_admin_user()

            self.is_initialized = True
            self.start_time = datetime.now()

            return True
        except Exception as e:
            print(f"Error initializing LMS system: {e}")
            return False

    def load_data(self) -> bool:
        """
        Load system data from persistence

        Returns:
            bool: Returns True if data loaded successfully, False otherwise
        """
        if not self.data_persistence:
            return False

        try:
            # Load data from persistence
            users_data = self.data_persistence.load_users()
            courses_data = self.data_persistence.load_courses()
            enrollments_data = self.data_persistence.load_enrollments()
            assignments_data = self.data_persistence.load_assignments()
            submissions_data = self.data_persistence.load_submissions()
            grades_data = self.data_persistence.load_grades()

            # Fill loaded data into managers
            if self.user_manager:
                # User data loaded through UserManager's load_users method
                self.user_manager.load_users()
                print(f"Loaded {len(self.user_manager.users)} users")

            if self.course_manager and courses_data:
                loaded_count = 0
                for course_id, course_data in courses_data.items():
                    if isinstance(course_data, dict):
                        # 映射字段：将 title 映射为 name
                        if 'title' in course_data and 'name' not in course_data:
                            course_data['name'] = course_data.pop('title')
                        
                        # 检查必要字段
                        required_fields = ['course_id', 'name', 'description', 'teacher_id']
                        if not all(field in course_data for field in required_fields):
                            print(f"课程数据缺少必要字段: {course_data}")
                            continue
                        
                        # 过滤掉Course构造函数不需要的字段
                        valid_fields = ['course_id', 'name', 'description', 'teacher_id', 'max_students', 
                                      'instructor_name', 'credits', 'is_active', 'created_at', 'updated_at', 'student_ids']
                        filtered_data = {k: v for k, v in course_data.items() if k in valid_fields}
                        
                        # 使用from_dict方法创建课程对象以正确处理时间戳
                        try:
                            course = Course.from_dict(filtered_data)
                            self.course_manager.courses[course_id] = course
                            loaded_count += 1
                        except Exception as e:
                            print(f"创建课程时出错 {course_id}: {e}")
                            import traceback
                            traceback.print_exc()

            if self.enrollment_manager and enrollments_data:
                # 将选课数据转换为Enrollment对象并添加到选课管理器
                loaded_enrollments = 0
                for enrollment_id, enrollment_data in enrollments_data.items():
                    if isinstance(enrollment_data, dict):
                        try:
                            # 从字典数据创建Enrollment对象
                            from models.enrollment import Enrollment
                            enrollment = Enrollment.from_dict(enrollment_data)
                            self.enrollment_manager.enrollments[enrollment_id] = enrollment
                            loaded_enrollments += 1
                        except Exception as e:
                            print(f"创建选课对象时出错 {enrollment_id}: {e}")
                            # 如果创建失败，尝试直接存储字典（向后兼容）
                            self.enrollment_manager.enrollments[enrollment_id] = enrollment_data
                print(f"加载了 {loaded_enrollments} 个选课记录")
                
                # 重建选课索引
                if loaded_enrollments > 0:
                    self.enrollment_manager.rebuild_indexes()

            if self.assignment_manager and assignments_data:
                # 将作业数据转换为Assignment对象并添加到作业管理器
                loaded_assignments = 0
                for assignment_id, assignment_data in assignments_data.items():
                    if isinstance(assignment_data, dict):
                        try:
                            # 从字典数据创建Assignment对象
                            from models.assignment import Assignment
                            assignment = Assignment.from_dict(assignment_data)
                            self.assignment_manager.assignments[assignment_id] = assignment
                            loaded_assignments += 1
                        except Exception as e:
                            print(f"创建作业对象时出错 {assignment_id}: {e}")
                            # 如果创建失败，尝试直接存储字典（向后兼容）
                            self.assignment_manager.assignments[assignment_id] = assignment_data
                print(f"加载了 {loaded_assignments} 个作业")

            if self.assignment_manager and submissions_data:
                # 将提交数据转换为Submission对象并添加到作业管理器
                loaded_submissions = 0
                for submission_id, submission_data in submissions_data.items():
                    if isinstance(submission_data, dict):
                        try:
                            # 从字典数据创建Submission对象
                            from models.submission import Submission
                            submission = Submission.from_dict(submission_data)
                            self.assignment_manager.submissions[submission_id] = submission
                            loaded_submissions += 1
                        except Exception as e:
                            print(f"创建提交对象时出错 {submission_id}: {e}")
                            # 如果创建失败，尝试直接存储字典（向后兼容）
                            self.assignment_manager.submissions[submission_id] = submission_data
                print(f"加载了 {loaded_submissions} 个提交记录")

            if grades_data:
                # 成绩数据通常与提交记录关联，这里可以记录日志
                print(f"发现 {len(grades_data)} 个成绩记录（将与提交记录关联）")
                # 成绩数据在需要时可以从提交记录中提取，不需要单独存储在assignment_manager中

            return True
        except Exception as e:
            print(f"加载数据时出错: {e}")
            return False

    def save_data(self) -> bool:
        """
        将系统数据保存到持久化

        返回:
            bool: 如果数据保存成功返回True，否则返回False
        """
        if not self.data_persistence or not self.is_initialized:
            return False

        try:
            # 从管理器中获取数据
            users_data = {}
            courses_data = {}
            enrollments_data = {}
            assignments_data = {}
            submissions_data = {}
            grades_data = {}

            # 获取用户数据
            if self.user_manager:
                # 使用UserManager的save_users方法来保存完整的用户数据
                self.user_manager.save_users()

            # 获取课程数据
            if self.course_manager:
                for course_id, course in self.course_manager.courses.items():
                    courses_data[course_id] = {
                        'course_id': course.course_id,
                        'title': course.name,  # Changed from course.title to course.name
                        'description': course.description,
                        'teacher_id': course.teacher_id,
                        'max_students': course.max_students,
                        'current_students': course.get_student_count(),  # Use method instead of attribute
                        'instructor_name': course.instructor_name,
                        'credits': course.credits,
                        'is_active': course.is_active,
                        'created_at': course.created_at.isoformat(),
                        'updated_at': course.updated_at.isoformat() if course.updated_at else None
                    }

            # 获取选课数据
            if self.enrollment_manager:
                for enrollment_id, enrollment in self.enrollment_manager.enrollments.items():
                    if hasattr(enrollment, 'to_dict'):
                        enrollments_data[enrollment_id] = enrollment.to_dict()
                    else:
                        # 如果已经是字典格式，直接使用
                        enrollments_data[enrollment_id] = enrollment
                
                # 同时调用选课管理器自己的保存方法
                self.enrollment_manager.save_enrollments()

            # 获取作业数据
            if self.assignment_manager:
                for assignment_id, assignment in self.assignment_manager.assignments.items():
                    if hasattr(assignment, 'to_dict'):
                        assignments_data[assignment_id] = assignment.to_dict()
                    else:
                        # 如果已经是字典格式，直接使用
                        assignments_data[assignment_id] = assignment

                # 获取提交数据
                for submission_id, submission in self.assignment_manager.submissions.items():
                    if hasattr(submission, 'to_dict'):
                        submissions_data[submission_id] = submission.to_dict()
                    else:
                        # 如果已经是字典格式，直接使用
                        submissions_data[submission_id] = submission

                # 获取成绩数据（从提交中提取成绩信息）
                for submission_id, submission in self.assignment_manager.submissions.items():
                    if hasattr(submission, 'grade') and submission.grade is not None:
                        grades_data[submission_id] = {
                            'submission_id': submission_id,
                            'student_id': submission.student_id,
                            'assignment_id': submission.assignment_id,
                            'score': submission.grade,
                            'feedback': submission.feedback,
                            'graded_at': submission.graded_at.isoformat() if submission.graded_at else None
                        }

            # 保存数据到持久化
            if self.course_manager:
                self.data_persistence.save_courses(courses_data)
            if self.enrollment_manager:
                self.data_persistence.save_enrollments(enrollments_data)
            if self.assignment_manager:
                self.data_persistence.save_assignments(assignments_data)
                self.data_persistence.save_submissions(submissions_data)
                self.data_persistence.save_grades(grades_data)

            print("数据保存成功")
            return True
        except Exception as e:
            print(f"保存数据时出错: {e}")
            return False

    def run(self) -> None:
        """
        Run main system loop
        This method typically starts UI (CLI or GUI)
        """
        if not self.is_initialized:
            raise LMSException("System not initialized. Please call initialize() method first")

        print("GT-LMS system is running...")
        print(f"System start time: {self.start_time}")

        # This typically starts UI
        # Currently, we just print a message

    def shutdown(self) -> None:
        """
        优雅地关闭系统
        """
        try:
            # 关闭前保存数据
            self.save_data()

            # 清除系统状态
            self.is_initialized = False
            self.start_time = None

            print("GT-LMS系统关闭完成")
        except Exception as e:
            print(f"关闭过程中出错: {e}")

    def _ensure_admin_user(self) -> None:
        """
        确保系统中至少有一个管理员用户
        如果没有管理员用户，则创建一个默认管理员
        """
        try:
            # 检查是否已有管理员用户
            admin_users = []
            for user_id, user in self.user_manager.users.items():
                user_type = type(user).__name__
                print(f"检查用户 {user_id}: 类型={user_type}")
                if user_type == 'Admin':
                    admin_users.append(user)
            
            print(f"找到 {len(admin_users)} 个管理员用户")
            
            if not admin_users:
                print("系统中没有管理员用户，正在创建默认管理员...")
                
                # 创建默认管理员用户
                admin_data = {
                    'user_id': 'admin_002',  # 使用不同的ID避免冲突
                    'name': '系统管理员',
                    'email': 'admin@gtlms.com',
                    'password': 'admin123',  # 在实际应用中应该使用更安全的密码
                    'admin_level': 10  # 最高权限级别
                }
                
                admin_user = self.user_manager.create_user('admin', admin_data)
                if admin_user:
                    print(f"默认管理员创建成功: {admin_user.email}")
                    print("默认密码: admin123")
                    print("请登录后立即修改密码！")
                    
                    # 保存用户数据
                    self.user_manager.save_users()
                else:
                    print("默认管理员创建失败！")
            else:
                print(f"系统已检测到 {len(admin_users)} 个管理员用户")
                
        except Exception as e:
            print(f"检查管理员用户时出错: {e}")

    def get_statistics(self) -> Dict[str, Any]:
        """
        Get system statistics

        Returns:
            Dict[str, Any]: Dictionary containing system statistics
        """
        if not self.is_initialized:
            return {"error": "System not initialized"}

        stats = {
            "start_time": self.start_time.isoformat() if self.start_time else None,
            "uptime": str(datetime.now() - self.start_time) if self.start_time else "0",
            "users_count": len(self.user_manager.users) if self.user_manager else 0,
            "courses_count": len(self.course_manager.courses) if self.course_manager else 0,
            "enrollments_count": len(self.enrollment_manager.enrollments) if self.enrollment_manager else 0,
        }

        return stats

    def generate_report(self) -> str:
        """
        生成系统报告

        返回:
            str: 作为字符串的系统报告
        """
        stats = self.get_statistics()

        report = f"""
GT-LMS系统报告
====================
启动时间: {stats.get('start_time', 'N/A')}
运行时间: {stats.get('uptime', 'N/A')}
用户数: {stats.get('users_count', 0)}
课程数: {stats.get('courses_count', 0)}
选课数: {stats.get('enrollments_count', 0)}
        """

        return report.strip()

    def backup_system(self) -> bool:
        """
        备份整个系统数据

        返回:
            bool: 备份成功返回True，否则返回False
        """
        if not self.data_persistence:
            print("数据持久化不可用")
            return False

        try:
            result = self.data_persistence.backup_all()
            if result:
                print("系统数据备份成功")
            else:
                print("系统数据备份失败")
            return result
        except Exception as e:
            print(f"备份系统数据时出错: {e}")
            return False

    def list_backups(self) -> list:
        """
        列出所有备份

        返回:
            list: 备份列表
        """
        if not self.data_persistence:
            return []

        try:
            return self.data_persistence.list_backups()
        except Exception as e:
            print(f"列出备份时出错: {e}")
            return []

    def restore_from_backup(self, backup_name: str) -> bool:
        """
        从备份恢复数据

        参数:
            backup_name (str): 备份名称

        返回:
            bool: 恢复成功返回True，否则返回False
        """
        if not self.data_persistence:
            print("数据持久化不可用")
            return False

        try:
            result = self.data_persistence.restore_from_backup(backup_name)
            if result:
                print(f"从备份 {backup_name} 恢复数据成功")
                # 重新加载数据
                self.load_data()
            else:
                print(f"从备份 {backup_name} 恢复数据失败")
            return result
        except Exception as e:
            print(f"从备份恢复数据时出错: {e}")
            return False

    def create_test_data(self) -> bool:
        """
        创建测试数据用于演示

        返回:
            bool: 如果测试数据创建成功返回True，否则返回False
        """
        try:
            if not self.is_system_ready():
                print("系统未准备好，无法创建测试数据")
                return False

            # 创建测试用户
            admin_data = {
                'user_id': 'admin_001',
                'name': '系统管理员',
                'email': 'admin@gt-lms.edu',
                'password': 'Admin123!',
                'admin_level': 10
            }

            teacher_data1 = {
                'user_id': 'teacher_001',
                'name': '张老师',
                'email': 'zhang@gt-lms.edu',
                'password': 'Teacher123!',
                'employee_id': 'T001',
                'department': '计算机科学系'
            }

            teacher_data2 = {
                'user_id': 'teacher_002',
                'name': '李老师',
                'email': 'li@gt-lms.edu',
                'password': 'Teacher123!',
                'employee_id': 'T002',
                'department': '数学系'
            }

            student_data1 = {
                'user_id': 'student_001',
                'name': '小明',
                'email': 'xiaoming@gt-lms.edu',
                'password': 'Student123!',
                'student_number': 'S2023001',
                'major': '计算机科学',
                'enrollment_year': 2023
            }

            student_data2 = {
                'user_id': 'student_002',
                'name': '小红',
                'email': 'xiaohong@gt-lms.edu',
                'password': 'Student123!',
                'student_number': 'S2023002',
                'major': '数学',
                'enrollment_year': 2023
            }

            student_data3 = {
                'user_id': 'student_003',
                'name': '小刚',
                'email': 'xiaogang@gt-lms.edu',
                'password': 'Student123!',
                'student_number': 'S2023003',
                'major': '计算机科学',
                'enrollment_year': 2023
            }

            # 创建用户
            self.user_manager.create_user('admin', admin_data)
            self.user_manager.create_user('teacher', teacher_data1)
            self.user_manager.create_user('teacher', teacher_data2)
            self.user_manager.create_user('student', student_data1)
            self.user_manager.create_user('student', student_data2)
            self.user_manager.create_user('student', student_data3)

            print("测试用户创建完成")

            # 创建测试课程
            course1 = self.course_manager.create_course(
                name='Python程序设计',
                description='Python编程基础课程',
                teacher_id='teacher_001',
                max_students=30
            )

            course2 = self.course_manager.create_course(
                name='高等数学',
                description='微积分和线性代数',
                teacher_id='teacher_002',
                max_students=50
            )

            course3 = self.course_manager.create_course(
                name='数据结构与算法',
                description='数据结构和算法分析',
                teacher_id='teacher_001',
                max_students=25
            )

            print("测试课程创建完成")

            # 创建测试选课记录
            self.enrollment_manager.create_enrollment('student_001', 'course_001')
            self.enrollment_manager.create_enrollment('student_001', 'course_002')
            self.enrollment_manager.create_enrollment('student_002', 'course_002')
            self.enrollment_manager.create_enrollment('student_003', 'course_001')
            self.enrollment_manager.create_enrollment('student_003', 'course_003')

            print("测试选课记录创建完成")

            return True
        except Exception as e:
            print(f"创建测试数据时出错: {e}")
            return False

    def get_user_manager(self):
        """
        获取用户管理器实例

        返回:
            UserManager: 用户管理器实例
        """
        return self.user_manager

    def get_course_manager(self):
        """
        获取课程管理器实例

        返回:
            CourseManager: 课程管理器实例
        """
        return self.course_manager

    def get_enrollment_manager(self):
        """
        获取选课管理器实例

        返回:
            EnrollmentManager: 选课管理器实例
        """
        return self.enrollment_manager

    def get_assignment_manager(self):
        """
        获取作业管理器实例

        返回:
            AssignmentManager: 作业管理器实例
        """
        return self.assignment_manager

    def get_auth_system(self):
        """
        获取认证系统实例

        返回:
            AuthenticationSystem: 认证系统实例
        """
        return self.auth_system

    def get_data_persistence(self):
        """
        获取数据持久化实例

        返回:
            DataPersistence: 数据持久化实例
        """
        return self.data_persistence

    def is_system_ready(self) -> bool:
        """
        Check if system is ready

        Returns:
            bool: Returns True if system is ready, False otherwise
        """
        return (self.is_initialized and
                self.user_manager is not None and
                self.course_manager is not None and
                self.enrollment_manager is not None and
                self.assignment_manager is not None and
                self.auth_system is not None and
                self.data_persistence is not None)

    def get_configuration(self) -> dict:
        """
        Get system configuration information

        Returns:
            dict: Dictionary containing system configuration information
        """
        config = {
            "System Name": "GT-LMS Learning Management System",
            "Version": "1.0.0",
            "Initialization Status": "Initialized" if self.is_initialized else "Not Initialized",
            "Start Time": self.start_time.strftime("%Y-%m-%d %H:%M:%S") if self.start_time else "N/A",
            "Session Timeout": f"{self.auth_system.session_timeout} seconds" if self.auth_system else "N/A",
            "Data Persistence": "Enabled" if self.data_persistence else "Disabled",
            "User Manager": "Loaded" if self.user_manager else "Not Loaded",
            "Course Manager": "Loaded" if self.course_manager else "Not Loaded",
            "Enrollment Manager": "Loaded" if self.enrollment_manager else "Not Loaded",
            "Assignment Manager": "Loaded" if self.assignment_manager else "Not Loaded",
        }
        
        # Get statistics
        stats = self.get_statistics()
        config.update({
            "Total Users": stats.get('users_count', 0),
            "Total Courses": stats.get('courses_count', 0),
            "Total Enrollments": stats.get('enrollments_count', 0),
        })
        
        return config